import P from "@/scenario/monitor/plotUtils";
import { ArcType, Cartesian3, HeightReference, Math as cesiumMath, PolylineArrowMaterialProperty, Viewer, defined, Ellipsoid, Transforms, Matrix4 } from "cesium";
import { Math } from "core-js";
import { cE } from "naive-ui";

export default {
    /**
     * 转换 地球使用点为经纬度
     * @param {Cartesian3} cartesian3
     * @param {Viewer} curViewer 
     * @return 
     */
    convertC3ToPosition(cartesian3,curViewer){
        let ellipsoid= Ellipsoid.WGS84;
        if (curViewer) {
            ellipsoid= curViewer.scene.globe.ellipsoid;
        }
        
        let cartographic=ellipsoid.cartesianToCartographic(cartesian3);
        //获得海拔
        if (curViewer) {
            cartographic.height = curViewer.scene.globe.getHeight(cartographic);
            if(cartographic.height == undefined || cartographic.height == NaN){
                cartographic.height = 0;
            }
        }else{
            cartographic.height = 0;
        }
       
        return {
            longitude:cesiumMath.toDegrees(cartographic.longitude),
            latitude:cesiumMath.toDegrees(cartographic.latitude),
            height:cartographic.height
        };
    },
    /**
      * 点数组转成json,方便存储
      * @param {Array} poss
      */
    toJsonForPositions(poss,curViewer) {
        let positions = [];
        for (let i = 0; i < poss.length; i++) {
            let pos = this.toJsonForPosition(poss[i],curViewer);
            positions.push(pos);
        }
        return positions;
    },
    /**
     * 单独转position到json
     * @param {Cartesian3} position
     * @param curViewer
     */
    toJsonForPosition(position,curViewer) {
        return this.convertC3ToPosition(position,curViewer);
    },
    /**
     * 替换全部匹配字符
     * @param text {String} 原字符
     * @param regChar {String} 要匹配的字符
     * @param replaceChar {String} 要替换的字符
     */
    textReplaceAll(text, regChar, replaceChar) {
        while (text.indexOf(regChar) !== -1) {
            text = text.replace(regChar, replaceChar);
        }
        return text;
    },
    /**
     * json 数据反转为对象数组
     * @param positionStrings {String}
     * @return {[]}
     */
    recodingPositions(positionStrings) {
        let positions = [];
        let positionsJson = JSON.parse(positionStrings);
        for (let i = 0; i < positionsJson.length; i++) {
            let cartesian3 = this.reCodingPostion(positionsJson[i]);
            positions.push(cartesian3);
        }
        return positions;
    },
    /**
     * json 反写为 Cartesisan3 对象
     * @param positonString
     * @return {Cartesian3}
     */
    reCodingPostion(positonString) {
        let posJson = positonString;
        if ($.type(positonString).toLowerCase() === "string") {
            posJson = JSON.parse(positonString);
        }
        return Cartesian3.fromDegrees(Number.parseFloat(posJson.longitude), Number.parseFloat(posJson.latitude));
    },
    /**
     * 生成UUID
     * @return {string}
     */
    creatUUID() {
        const len = 32;
        let radix = 16;
        let chars = '0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'.split("")
        let uuid = [];
        radix = radix || chars.length;
        if (len) {
            for (let i = 0; i < len; i++) {
                uuid[i] = chars[0 | Math.random() * radix];
            }
        } else {
            let r;
            uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
            uuid[14] = '4';
            for (let i = 0; i < 36; i++) {
                if (!uuid[i]) {
                    r = 0 | Math.random() * 16;
                    uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r];
                }
            }
        }
        return uuid.join('');
    },
    /**
     * 检查某个数组中是否包含指定元素
     * @param array {[]}
     * @param arrayElement 要检查的元素
     * @param checkFunction 匹配函数，用来做对比
     */
    checkArrayContain(array, arrayElement, checkFunction) {
        let flag = false;
        for (let i = 0; i < array.length; i++) {
            let arrayElem = array[i];
            if (checkFunction(arrayElem, arrayElement)) {
                flag = true;
                break;
            }
        }
        return flag;
    },

    /**
     * 通过一个筛选函数，筛选出合格的单一数据
     * @param array {[]}
     * @param checkFunction 检查函数
     */
    findElementFromArray(array, checkFunction) {
        let findElem = undefined;
        for (let i = 0; i < array.length; i++) {
            let arrayElement = array[i];
            if (checkFunction(arrayElement)) {
                findElem = arrayElement;
                break;
            }
        }
        return findElem;
    },
    /**
     * 定位到指定经纬度
     * @param {Number} lon  经度
     * @param {NUmber} lat  纬度
     * @param {Number} height 高度
     * @param curViewer
     */
    positionLocation(lon, lat,height=500000,curViewer) {
        let cartesian3 = new Cartesian3.fromDegrees(lon, lat, height);
        curViewer.camera.flyTo({
            destination: cartesian3,
            duration: 5,
            endTransform: Cesium.Matrix4.IDENTITY
        });
    },
    /**
     * 选择器框选指定实体
     * @param checkEntity {Entity} 确定的Cesium 实体
     */
    selectionAnimateAppear(curViewer, checkEntity) {
        curViewer._selectedEntity = checkEntity;
        let selectionIndicator = curViewer.selectionIndicator.viewModel;
        if (selectionIndicator) {
            selectionIndicator.animateAppear();
        }
        curViewer._selectedEntityChanged.raiseEvent(checkEntity);
    },
    /**
     * 判断是否点击在地球上
     * @param position
     */
    judgeClickPosition(position, curViewer) {
        let flag = true;
        if (!defined(position)) {
            return false;
        }
        let ray = curViewer.camera.getPickRay(position);
        if (!defined(ray)) {
            return false;
        }

        if (flag) {
            return {
                pos: position,
                ray: ray
            };
        } else {
            return flag;
        }
    },
    /**
     * 判断是否点击到实体
     * @param v
     * @param position
     * @return {boolean|*}
     */
    judgeClickEntity(v, position) {
        let flag = true;
        let pickedObjects = v.scene.drillPick(position);   
        if (!pickedObjects || !defined(pickedObjects[0]) || !defined(pickedObjects[0].id)) {
            return false;
        }
        const geoDataSource = v.dataSources.get(0);
        //排除geo的ENtity
        let pickedObject = this.findElementFromArray(pickedObjects, e => !geoDataSource.entities.contains(e.id));
        
        if(!pickedObject || !defined(pickedObject) || !defined(pickedObject.id)){
            return false;
        }

        let entity = pickedObject.id;

        if (!flag) {
            return false;
        } else {
            return entity;
        }
    },
    /**
     * map 转为 array
     * @param map {Map}
     * @param isSaveKey {Boolean}
     */
    converMapToArray(map, isSaveKey) {
        let keys = [];
        let values = [];

        for (let key of map.keys()) {
            keys.push(key);
            values.push(map.get(key));
        }
        if (isSaveKey) {
            return {
                keys: keys,
                values: values
            }
        } else {
            return values;
        }
    },
    /**
     * 以一个点为中心，旋转另一个点，方便计算
     * @param center {(Number)[]}
     * @param rotatePos {(Number)[]}
     * @param rotateAngle {Number}
     * @return {(Number)[]}
     * @private
     */
    rotateAroundCenter(center, rotatePos, rotateAngle) {
        let len = P.PlotUtils.distance(center, rotatePos);
        let azi = P.PlotUtils.getAzimuth(center, rotatePos);
        azi = cesiumMath.toDegrees(azi);
        let newAzi = azi + rotateAngle;
        let lon = len * cesiumMath.cos(Math.toRadians(newAzi));
        let lat = len * cesiumMath.sin(Math.toRadians(newAzi));
        return [center[0] + lon, center[1] + lat];
    },
    getLonLatWithViewer: function (cartesian,curViewer) {
        let cartographic = curViewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
        cartographic.height = curViewer.scene.globe.getHeight(cartographic);
        let pos = {
            lon: cartographic.longitude,
            lat: cartographic.latitude,
            alt: cartographic.height
        };
        pos.lon = cesiumMath.toDegrees(pos.lon);
        pos.lat = cesiumMath.toDegrees(pos.lat);
        return pos;
    },
    getLonLatArr(positions,curViewer) {
        let arr = [];
        for (let i = 0; i < positions.length; i++) {
            let p = this.convertC3ToPosition(positions[i],curViewer);
            if (p) {
                arr.push([p.longitude, p.latitude]);
            }
        }
        return arr;
    },
    /**
     * 创建一个点
     * @param position
     * @param color
     * @param params
     * @return {*}
     */
    drawPoint(curViewer, position, color, params) {
        let data = {
            position: position,
            point: {
                color: color,
                pixelSize: 5,
                heightReference: HeightReference.CLAMP_TO_GROUND
            }
        };
        if (params) {
            for (let k in params) {
                data[k] = params[k];
            }
        }
        return curViewer.entities.add(data);
    },
    /**
     * 画出箭头
     * @param curViewer
     * @param arrowPositions
     * @param params
     * @return {*}
     */
    drawArrow(curViewer, arrowPositions, params) {
        let _this = this;
        var entityData = {
            polyline: {
                positions: arrowPositions,
                material: new PolylineArrowMaterialProperty(Cesium.Color.RED.withAlpha(.8)),
                width: 5.0,
                clampToGround: true,
                arcType: Cesium.ArcType.GEODESIC
            }
        };
        if (params) {
            for (let k in params) {
                entityData[k] = params[k];
            }
        }
        return curViewer.entities.add(entityData);
    },
    /**
     * 创建单一的线
     * @param poss
     */
    drawPloyline(curViewer, poss, material, params) {
        let polylineData = {
            polyline: {
                positions: poss,
                material: material,
                width: 1.0,
                clampToGround: true,
                arcType: ArcType.GEODESIC
            }
        };

        if (params) {
            for (let k in params) {
                polylineData[k] = params[k];
            }
        }

        return polylineEntit = curViewer.entities.add(polylineData);
    },
    getLonLat (cartesian) {
        const ellipsoid = Ellipsoid.WGS84;
        let cartographic = ellipsoid.cartesianToCartographic(cartesian);
        let pos = {
            lon: cartographic.longitude,
            lat: cartographic.latitude,
            alt: 0
        };
        pos.lon = cesiumMath.toDegrees(pos.lon);
        pos.lat = cesiumMath.toDegrees(pos.lat);
        return [pos.lon,pos.lat];
    },
    /**
     * 以一个点，计算另个点的夹角，以x为 0 
     * @param {Cartesian3} center 
     * @param {Cartesian3} pos 
     */
    costIncludedAngle(center , pos){
        const centerLonLat = this.getLonLat(center);
        const posLonLat = this.getLonLat(pos);

        const a = P.PlotUtils.getAzimuthOne(centerLonLat,posLonLat);
        // console.log(cesiumMath.toDegrees(a));
        return a;   
        //如果不对，就要进行转换
        // return cesiumMath.toRadians(a);
    },
    /**
     * 起始点和时间速度，方位，计算下一个点
     * @param {Cartesian3} startCartesian 
     * @param  t 
     * @param  v 
     * @param  headingRad 
     * @returns {Cartesian3}
     */
    calculateNextPosition(startCartesian, t, v, headingRad) {
        const ellipsoid = Ellipsoid.WGS84;
        //地球半径
        const r = ellipsoid.maximumRadius;

        // 以开始的点为原点，建立坐标系，以正北为0夹角，开始计算下一个点
    
        // 计算位移距离
        const distance = v * t;
        const rd = distance/r;        
        // 分解方位角到东向和北向分量（Cesium的heading是正北0，顺时针增加）
        const dEast = rd * Math.sin(headingRad);
        const dNorth = rd * Math.cos(headingRad);
        
        const pos =ellipsoid.cartesianToCartographic(startCartesian);
        pos.latitude += dEast;
        pos.longitude += dNorth;
        pos.height = 0
        
        return ellipsoid.cartographicToCartesian(pos);
    },
    /**
     * 消除海拔
     * @param {Cartesian3} cartesian 
     */
    clearHeight(cartesian){
        if(!cartesian.x){
            return undefined;
        }
        const ellipsoid = Ellipsoid.WGS84;
        let cartographic=ellipsoid.cartesianToCartographic(cartesian);
        //获得海拔
        cartographic.height = 0;

        return ellipsoid.cartographicToCartesian(cartographic);
    },
    /**
     * 日期格式化
     * @param regExp 格式化字符串
     * @param date {Date} 日期
     */
    dateFormat(date, regExp) {
        if (!regExp) {
            regExp = "yyyy-MM-dd HH:mm:ss";
        }
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const dateOne = date.getDate();
        const hours = date.getHours();
        const minutes = date.getMinutes();
        const sec = date.getSeconds();

        function converNum(number) {
            let n = "" + number;
            if (number < 10) {
                n = "0" + number;
            }
            return n;
        }

        return regExp.replace("yyyy", year).replace("MM", converNum(month))
            .replace("dd", converNum(dateOne)).replace("HH", converNum(hours))
            .replace("mm", converNum(minutes)).replace("ss", converNum(sec));
    }
}